home *** CD-ROM | disk | FTP | other *** search
- Subject: v11i101: Graphics editor for Suns, Part05/06
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: steinmetz!sbcs!nyfca1!chan (Douglas Chan)
- Posting-number: Volume 11, Issue 101
- Archive-name: graphedit/part05
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # Contents: display.c ps.c pic.c plot.c
-
- echo x - display.c
- sed 's/^@//' > "display.c" <<'@//E*O*F display.c//'
-
- static char SccsId[] = "@(#)display.c 1.1 6/8/87 Copyright 1987 SBCS-chan";
-
- /*****************************************************************************
-
- (c) Copyright 1987
-
- Lap-Tak Chan
- Computer Science Department
- State University of New York at Stony Brook
- Stony Brook, NY 11794
-
- This software and its documentation may be used, copied, and
- distributed, provided that this legend appear in all copies and
- that it is not copied or distributed for a profit.
-
- No representations is made about the suitability of this software
- for any purpose. It is provided "as is" with no support and no
- express or implied warranty.
-
- *****************************************************************************/
-
- /*****************************************************************************
-
- Display List
- ============
-
- The display list is used to maintain the data structure used to store
- the segments internally. Each segment has a display list, which
- consists of its segment number, attributes, and a instruction list.
- Each instruction is composed of an instruction with two arguments.
-
- The display list is initialized with ge_init_display. A segment is
- opened with ge_new_segment. Output primitives are drawn with ge_graph
- which will appending them to the instruction list of the segment.
- ge_delete_segment will delete the segment and free the memory allocated
- to the segment to the internal free lists. ge_display_list will return
- a pointer to the display list of a segment.
-
- The display list maintains a list of segments, which is
- a simple linked list of segment blocks taken from a fixed array.
- Unused segment blocks in the array are linked on a free list.
- Each segment block stores a pointer to the node of the object, the
- current position of the segment and a instruction list of the segment.
- The instruction list is stored as a circular queue of display items.
- Each display item consists of a display instruction and a coordinate.
-
- A hash table should be used to reference the segments instead of
- a search on the segment list.
-
- *****************************************************************************/
-
- #include "display.h"
- #define GE_DITEM_SIZE 50 /* number of items to obtain from calloc when
- free list is empty */
-
- struct list ge_open[GE_OPENMAX+1]; /* array of display lists */
- static struct list_item *ge_dfree=0; /* free list for display instructions */
- static int ge_dsfree; /* free list for segment blocks */
- int ge_seglist; /* list of segment blocks */
- /* instruction to indicate close of segment */
- static struct list_item closeinstr;
-
- /*****************************************************************************
-
- Display items have to be allocated and freed frequently. The C
- allocation routines alloc, calloc and free is not efficient. To increase
- the efficiency, a list of free display items is maintained. Requests for
- display item are allocated from the free list. When the free list is
- empty, a number of display items is obtained with calloc and linked to
- the free list.
-
- ge_get_item will return a display item which is not in use. It obtains
- the display item from the free list. When the free list is empty, it
- get a number of display item from the system with calloc and link
- them to the free list.
-
- *****************************************************************************/
-
- struct list_item *ge_get_item()
- {
- struct list_item *tmp;
- int count;
-
- /* free list is empty */
- if ( ! ge_dfree ) {
-
- /* get space for list items */
- tmp = (struct list_item *)calloc(GE_DITEM_SIZE,sizeof(struct list_item));
-
- /* link blocks on free list */
- for(count=1;count < GE_DITEM_SIZE;count++)
- tmp[count].next = &(tmp[count-1]);
- ge_dfree = &(tmp[GE_DITEM_SIZE-1]);
- }
-
- /* get item from free list */
- tmp=ge_dfree;
- ge_dfree=tmp->next;
- return (tmp);
-
- }
-
- /*****************************************************************************
-
- ge_free_item will release a display item to the free list.
-
- *****************************************************************************/
-
- ge_free_item(ptr)
- struct list_item *ptr;
- {
-
- ptr->next = ge_dfree;
- ge_dfree = ptr;
-
- }
-
- /*****************************************************************************
-
- ge_init_display initializes the display list. It links the segment blocks
- on the array to form a free list.
-
- *****************************************************************************/
-
- ge_init_display()
- {
- int i;
-
- /* link segment blocks to form free list */
- for(i=0;i<GE_OPENMAX-1;i++)
- ge_open[i].next = i + 1;
- ge_dsfree=1;
-
- /* empty segment list */
- ge_seglist=0;
-
- closeinstr.instr=GE_CLOSE;
-
- }
-
- /*****************************************************************************
-
- ge_index searches for the display list of a segment.
-
- input
- segno : segment number
-
- output
- ge_index returns pointer to display list if found
-
- *****************************************************************************/
-
- int ge_index(segno)
- int segno;
- {
- int i;
-
- for ( i=ge_seglist; i && ge_open[i].segno != segno; i=ge_open[i].next );
- if ( ge_open[i].segno == segno ){
- return (i);
- }
- else {
- return(-1);
- }
- }
-
- /*****************************************************************************
-
- ge_new_segment is called to create a new segment.
-
- input
- tree : pointer to node of object
-
- *****************************************************************************/
-
- ge_new_segment(segno)
- int segno;
- {
- int pos;
-
- /* remove segment from free list */
- pos=ge_dsfree;
- ge_dsfree=ge_open[pos].next;
-
- /* add segment to segment list */
- ge_open[pos].next = ge_seglist;
- ge_seglist = pos;
-
- /* initialize content of list */
- ge_open[pos].d_list = 0;
-
- ge_open[pos].segno = segno;
-
- }
-
- /*****************************************************************************
-
- ge_graph will add an output primitive to the display list of a segment.
-
- input
- segno : segment number
- instr : display instruction of output primitive (polygon, line, move, etc)
- x,y : coordinate of display
-
- *****************************************************************************/
-
- ge_graph(segno,instr,x,y)
- int segno, instr;
- float x,y;
- {
- int pos;
- struct list_item *ptr;
-
- /* get display list of segment */
- if ( (pos = ge_index(segno))>=0 ) {
-
- /* get display item */
- ptr = ge_get_item();
-
- /* store instruction and coordinate in item */
- ptr->instr=instr;
- ptr->x=x;
- ptr->y=y;
-
- /* add instruction to display list */
- if ( ge_open[pos].d_list ) {
- ptr->next = ge_open[pos].d_list->next;
- ge_open[pos].d_list->next = ptr;
- }
- else ptr->next = ptr;
- ge_open[pos].d_list = ptr;
-
- }
-
- } /* ge_graph */
-
- /*****************************************************************************
-
- ge_delete_segment is called to delete a segment from the display list.
-
- input
- segno : segment number
-
- *****************************************************************************/
-
- ge_delete_segment(segno)
- int segno;
- {
-
- int pos,tmpseg;
- struct list_item *ptr,*tmp;
-
- /* search for display list of segment */
- if ( pos=ge_index(segno) ) {
-
- /* delete segment block from list of segments */
- if ( pos == ge_seglist ) {
- /* segment at beginning of list */
- ge_seglist = ge_open[pos].next;
- }
- else {
- for (tmpseg=ge_seglist; (ge_open[tmpseg].next != pos);
- tmpseg=ge_open[tmpseg].next) ;
- ge_open[tmpseg].next = ge_open[pos].next;
- }
-
- /* free display list of segment */
- if ( ge_open[pos].d_list ) {
-
- /* make the display list a simple linked list */
- ptr=ge_open[pos].d_list->next;
- ge_open[pos].d_list->next = 0;
-
- /* free items along the list */
- for ( ; ptr; ptr=tmp ) {
- tmp=ptr->next;
- ge_free_item(ptr);
- }
-
- } /* if */
-
- /* add segment block to free list */
- ge_open[pos].next = ge_dsfree;
- ge_dsfree = pos;
-
- } /* if */
-
- } /* ge_delete_segment */
-
- /*****************************************************************************
-
- ge_display_list will get the display list of a segment.
-
- Input
- segno - number of segment
-
- Output
- Return pointer to display list of segment, 0 if segment is not found.
-
- *****************************************************************************/
-
- struct list *ge_display_list(segno)
- int segno;
- {
- int pos;
-
- if ((pos=ge_index(segno)) >= 0) {
- return(&(ge_open[pos]));
- }
- else
- return(0);
-
- } /* ge_display_list */
- @//E*O*F display.c//
- chmod u=r,g=r,o=r display.c
-
- echo x - ps.c
- sed 's/^@//' > "ps.c" <<'@//E*O*F ps.c//'
-
- static char SccsId[] = "@(#)ps.c 1.2 6/8/87 Copyright 1987 SBCS-chan";
-
- /*****************************************************************************
-
- (c) Copyright 1987
-
- Lap-Tak Chan
- Computer Science Department
- State University of New York at Stony Brook
- Stony Brook, NY 11794
-
- This software and its documentation may be used, copied, and
- distributed, provided that this legend appear in all copies and
- that it is not copied or distributed for a profit.
-
- No representations is made about the suitability of this software
- for any purpose. It is provided "as is" with no support and no
- express or implied warranty.
-
- *****************************************************************************/
-
- /*****************************************************************************
-
- PostScript Interface
- ====================
-
- This file contains the PostScript interface routines of graphedit
- which can write the display lists in PostScript and rebuild the display
- lists from the written PostScript.
-
- *****************************************************************************/
-
- #include "display.h"
- #include <usercore.h>
- #include <stdio.h>
- #include <string.h>
-
- #define DEGPERRAD 180./PI
- #define PSHEADER "ps.head" /* name of the header file */
- static FILE *writefile;
- static char pshead[80];
- struct list *ge_display_list();
-
- /*****************************************************************************
-
- ps_init do the necessary initialization before writing segments to the
- output file. It will copy the header file as the beginning of the output
- file, and define how the graphedit coordinate system will be put on
- 8.5 x 11 paper according to save_attr.
-
- *****************************************************************************/
-
- ps_init()
- {
- float sx, sy, tx, ty;
- FILE *header;
- char buf[512];
- extern struct saveattr save_attr;
- float width, height;
-
- /* copy header to output file */
- if ( ! (header=fopen(pshead, "r"))) {
- fprintf(writefile, "%% Header file %s should be included here\n",pshead);
- }
- else {
-
- /* copy the header file to the output file */
- while ( fgets(buf, 512, header) ) {
- fputs(buf, writefile);
- }
- /* close the header file */
- fclose(header);
- }
-
- if ( save_attr.rotate ) {
-
- /* rotate picture */
- width = save_attr.height;
- height = save_attr.width;
-
- /* determine the scale, height and width of picture */
- sx=save_attr.height*7.2/GE_WIN_X;
- sy=save_attr.width*7.2/GE_WIN_Y;
- switch ( save_attr.fix ) {
- case 1:
- sx=sy;
- width=GE_WIN_X/GE_WIN_Y*height;
- break;
- case 2:
- sy=sx;
- height=GE_WIN_Y/GE_WIN_X*width;
- break;
- } /* switch */
-
- /* determine the offset necessary */
- if ( save_attr.center ) {
- tx = (55./width-0.5)*GE_WIN_X;
- ty = (-42.5/height-0.5)*GE_WIN_Y;
- }
- else {
- tx = ((110.-save_attr.offb)/width-1.)*GE_WIN_X;
- ty = ((-save_attr.offa)/height-1.)*GE_WIN_Y;
- }
-
- fprintf(writefile, "90. rotate ");
-
- }
-
- else {
- width = save_attr.width;
- height = save_attr.height;
-
- /* determine the scale, height and width of the picture */
- sx=save_attr.width*7.2/GE_WIN_X;
- sy=save_attr.height*7.2/GE_WIN_Y;
- switch (save_attr.fix) {
- case 1:
- sy=sx;
- height=GE_WIN_Y/GE_WIN_X*width;
- break;
- case 2:
- sx=sy;
- width=GE_WIN_X/GE_WIN_Y*height;
- break;
- } /* switch */
-
- /* determine the offset necessary */
- if ( save_attr.center ) {
- tx = (42.5/width-0.5)*GE_WIN_X;
- ty = (55./height-0.5)*GE_WIN_Y;
- }
- else {
- tx = save_attr.offa/width*GE_WIN_X;
- ty = ((110.-save_attr.offb)/height-1.)*GE_WIN_Y;
- }
-
- }
-
- /* define the graphedit coordinate system */
- fprintf(writefile, "%f %f scale %f %f translate\n", sx, sy,
- tx,ty);
-
- /* header which will be used to find the real beginning of the
- saved segments */
- fprintf(writefile, "%% graphedit.save v%s\n", GE_VERSION);
-
- } /* ps_init */
-
- /*****************************************************************************
-
- ps_done just do whatever necessary after saving all these segments.
-
- *****************************************************************************/
-
- ps_done()
- {
- FILE *tail;
- char buf[512];
-
- fprintf(writefile, "GE_TERM\n");
-
- } /* ps_done */
-
- /*****************************************************************************
-
- ps_setfont will generate the change of font in PostScript.
-
- *****************************************************************************/
-
- ps_setfont(font)
- int font;
- {
-
- fprintf(writefile, "%d GE_SET_FONT\n", font);
-
- } /* ps_setfont */
-
- /*****************************************************************************
-
- ps_setlinestyle will generate the change of line style in PostScript.
-
- *****************************************************************************/
-
- ps_setlinestyle(type)
- int type;
- {
-
- fprintf(writefile, "%d GE_SET_LINESTYLE\n", type);
-
- } /* ps_setlinestyle */
-
- /*****************************************************************************
-
- ps_draw_seg will draw a segment in PostScript according to its display
- list.
-
- Input
- list - display list of segment
-
- *****************************************************************************/
-
- ps_draw_seg(list)
- struct list *list;
- {
- struct list_item *ptr;
- static struct list_item closeinstr={GE_CLOSE, 0., 0., NULL};
-
- /* abort if the display list of the segment is empty */
- if ( !(ptr=list->d_list) )
- return;
-
- /* set the transformation of the segment */
- fprintf(writefile, "GE_NEW_SEG\n%f %f GE_TRANSLATE\n%f GE_ROTATE\n%f %f GE_SCALE\n",
- list->attr.tx, list->attr.ty, list->attr.ang * DEGPERRAD,
- list->attr.sx, list->attr.sy);
-
- /* set the attribtes of the segment */
- fprintf(writefile, "%d GE_SET_COLOR\n", list->attr.color);
- fprintf(writefile, "%d GE_SET_LINEWIDTH\n",
- list->attr.linewidth);
- fprintf(writefile, "%d GE_SET_CHARSIZE\n", list->attr.charsize);
- ps_setlinestyle(list->attr.linestyle);
- ps_setfont(list->attr.font);
-
- /* scan the display list and execute the instructions to draw the
- primitives */
- ptr=ptr->next;
- do {
- ps_exec(ptr);
- ptr=ptr->next;
- } while ( ptr != list->d_list->next );
-
- /* close the segment */
- ps_exec(&closeinstr);
- fprintf(writefile, "GE_END_SEG\n");
-
- } /* ps_draw_seg */
-
- /*****************************************************************************
-
- ps_exec will execute an instruction and draw it in PostScript.
-
- Input
- ptr - pointer to instruction
-
- *****************************************************************************/
-
- ps_exec(ptr)
- struct list_item *ptr;
- {
- static float xbuff[512], ybuff[512];
- static int lastinstr=0;
- static int n=0;
- int i;
-
- /* execute last polyline/polygon instruction if instruction indicates
- end of the last instruction */
- if ( lastinstr && ptr->instr != GE_CONT ) {
- switch ( lastinstr ) {
-
- case GE_POLYLINE :
- fprintf(writefile, "%.4f %.4f GE_POLYLINE\n", xbuff[0], ybuff[0]);
- for (i=1; i<n; i++) {
- fprintf(writefile, "%.4f %.4f GE_CONT\n", xbuff[i], ybuff[i]);
- }
- fprintf(writefile, "GE_END\n");
- break;
-
- case GE_POLYGON:
- fprintf(writefile, "%.4f %.4f GE_POLYGON\n", xbuff[0], ybuff[0]);
- for (i=1; i<n; i++) {
- fprintf(writefile, "%.4f %.4f GE_CONT\n", xbuff[i], ybuff[i]);
- }
- fprintf(writefile, "GE_END\n");
- break;
-
- default: ;
- }
- lastinstr = n = 0;
- }
-
- /* execute new instruction */
- switch (ptr->instr) {
-
- /* instructions with single coordinate */
- case GE_MOVE:
- fprintf(writefile, "%.4f %.4f GE_MOVE\n", ptr->x, ptr->y);
- break;
-
- case GE_LINE:
- fprintf(writefile, "%.4f %.4f GE_LINE\n", ptr->x, ptr->y);
- break;
-
- case GE_ELLIPSE:
- fprintf(writefile, "%.4f %.4f GE_ELLIPSE\n", ptr->x, ptr->y);
- break;
-
- case GE_ARC:
- fprintf(writefile, "%.4f %.4f GE_ARC\n", ptr->x, ptr->y);
- break;
-
- case GE_ARCEXT:
- fprintf(writefile, "%.4f GE_ARCEXT\n", ptr->x);
- break;
-
- case GE_CIRCLE:
- fprintf(writefile, "%.4f GE_CIRCLE\n", ptr->x);
- break;
-
- /* instruction with two or more coordinates */
- case GE_POLYLINE:
- case GE_POLYGON:
- /* store instruction */
- lastinstr=ptr->instr;
-
- case GE_CONT:
- /* save coordinate of polyline/polygon */
- xbuff[n] = ptr->x;
- ybuff[n++] = ptr->y;
- break;
-
- case GE_TEXT:
- fprintf(writefile, "(%s) GE_TEXT\n", (char *)((int)ptr->x));
- break;
-
- case GE_SETCOLOR:
- fprintf(writefile, "%d GE_SET_COLOR\n", (int)ptr->x);
- break;
-
- case GE_SETTYPELINE:
- fprintf(writefile, "%d GE_SET_LINESTYLE\n", (int)ptr->x);
- break;
-
- case GE_SETLINEWIDTH:
- fprintf(writefile, "%d GE_SET_LINEWIDTH\n", (int)ptr->x);
- break;
-
- case GE_SETFONT:
- fprintf(writefile, "%d GE_SET_FONT\n", (int)ptr->x);
- break;
-
- case GE_SETCHARSIZE:
- fprintf(writefile, "%d GE_SET_CHARSIZE\n", (int)ptr->x);
- break;
-
- case GE_FILL:
- fprintf(writefile, "%d GE_FILL\n", (int)ptr->x);
- break;
-
- case GE_CLOSE:
- /* do nothing */
- break;
-
- default :
- /* check that all instructions are properly handled */
- fprintf(stderr,
- "Internal Error-Action for instruction %d missing.\n",
- ptr->instr);
- break;
-
- } /* switch */
-
- } /* ps_exec */
-
- /*****************************************************************************
-
- ps_write will write the picture as a complete PostScrip program in
- the already opened outfile. It will copy a header file to outfile,
- scan the segment list and write every segment (except the sample segments)
- in PostScript.
-
- The directory where the header file is located will be defined by the
- environment GELIB. If GELIB is not defined, GE_DEFAULTLIB will be used.
-
- Input
- outfile - opened output stream to write on
-
- *****************************************************************************/
-
- ps_write(outfile)
- FILE *outfile;
- {
- extern int ge_seglist;
- extern struct list ge_open[];
- int i;
- char *libdir;
-
- /* save it so that ps_exec will be able to access it */
- writefile=outfile;
-
- /* generate the name for the header file */
- if ( !(libdir = (char *)getenv("GELIB")) )
- libdir=GE_DEFAULTLIB;
- (void)strcpy(pshead,libdir);
- (void)strcat(pshead,"/");
- (void)strcat(pshead,PSHEADER);
-
- /* initialize */
- ps_init();
-
- /* scan the segment list and write every user segment */
- for ( i=ge_seglist; i; i=ge_open[i].next ) {
- if ( ge_open[i].segno >= GE_MIN_SEG && (! ge_open[i].attr.deleted) ) {
- ps_draw_seg(&(ge_open[i]));
- } /* if */
- } /* for */
-
- ps_done();
-
- } /* ps_write */
-
- /*****************************************************************************
-
- ps_write_seg will write one segment in PostScript to outfile. The
- output file is not a complete PostScrip program and thus cannot be printed.
-
- Input
- outfile - opened output stream to write on
- segno - segment to write
-
- *****************************************************************************/
-
- ps_write_seg(outfile, segno)
- FILE *outfile;
- int segno;
- {
- struct list *list;
-
- writefile=outfile;
-
- /* get display list of segment */
- list=ge_display_list(segno);
-
- /* write header */
- fprintf(writefile, "%% graphedit.save v%s\n", GE_VERSION);
-
- /* write segment in PostScript */
- ps_draw_seg(list);
-
- } /* ps_write_seg */
-
- /*****************************************************************************
-
- ps_load will rebuild the display list of the segments written in infile.
- It will scan the file for the mark of the beginning of data. Then it
- will read and process each line until the mark for the end of data is
- encountered.
-
- Input
- infile - opened input stread to read from
-
- *****************************************************************************/
-
- ps_load(infile)
- FILE *infile;
- {
- char inbuf[512];
-
- /* skip header until mark of beginning of data */
- for (; (fgets(inbuf,512,infile)) &&
- (strncmp(inbuf, "% graphedit.save",16)););
-
- if ( inbuf[0] != '%' ) {
- /* abort if header cannot be found */
- return(1);
- }
-
- /* read and process each line in infile until the instruction GE_TERM
- marking the end of the file is encountered */
- while ( (fgets(inbuf,512,infile) &&
- (strcmp(inbuf,"GE_TERM")) )) {
- /* process line */
- ps_read(inbuf);
- } /* while */
-
- return(0);
-
- } /* ps_load */
-
- /*****************************************************************************
-
- ps_cmd2instr will return the instruction for a command in the PostScript
- input.
-
- Input
- command - command in PostScript
-
- Output
- Return internal instruction corresponding to the command.
-
- *****************************************************************************/
-
- ps_cmd2instr(command)
- char *command;
- {
- struct cmdinstr {
- char *cmd;
- int instr;
- } ;
-
- /* a map of command to instruction */
- static struct cmdinstr cmdinstr[] = {
- { "GE_SET_FONT", GE_SETFONT },
- { "GE_SET_LINESTYLE", GE_SETTYPELINE },
- { "GE_SET_COLOR", GE_SETCOLOR },
- { "GE_SET_LINEWIDTH", GE_SETLINEWIDTH},
- { "GE_NEW_SEG", GE_NEW },
- { "GE_END_SEG", GE_CLOSE },
- { "GE_TRANSLATE", GE_TRANSLATE },
- { "GE_ROTATE", GE_ROTATE },
- { "GE_SCALE", GE_SCALE },
- { "GE_MOVE", GE_MOVE },
- { "GE_LINE", GE_LINE },
- { "GE_POLYLINE", GE_POLYLINE },
- { "GE_POLYGON", GE_POLYGON },
- { "GE_TEXT", GE_TEXT },
- { "GE_CIRCLE", GE_CIRCLE },
- { "GE_ELLIPSE", GE_ELLIPSE },
- { "GE_CONT", GE_CONT },
- { "GE_SET_CHARSIZE", GE_SETCHARSIZE },
- { "GE_FILL", GE_FILL },
- { "GE_ARC", GE_ARC },
- { "GE_ARCEXT", GE_ARCEXT},
- { "", 0 }
- };
-
- int i;
-
- /* scan for the location of the command in the map */
- for ( i=0; cmdinstr[i].instr && strcmp(cmdinstr[i].cmd, command); i++ );
-
- /* return instruction for command */
- return(cmdinstr[i].instr);
-
- } /* ps_cmd2instr */
-
- /*****************************************************************************
-
- ps_read will process a command in a line of input. Each command may
- be composed of 1 to 3 fields. The last field corresponds to an attribute
- or instruction while the others are parameters to the commands.
-
- Input
- inbuf - input buffer containing a line of input from the input file
-
- *****************************************************************************/
-
- ps_read(inbuf)
- char *inbuf;
- {
- static int ps_segno;
- static struct list *seginfo;
- char buf1[80], buf2[80], buf3[80], *command;
- int fields, instr, inexec;
- float x,y;
-
- /* handle GE_TEXT */
- if ( inbuf[0] == '(' ) {
-
- char *ptr;
-
- /* get the end of the text string */
- if ( ptr=(char *)rindex(inbuf,')') ) {
-
- *ptr='\0';
- strcpy((ptr=(char *)malloc(strlen(inbuf))),&(inbuf[1]));
- ge_graph(ps_segno, GE_TEXT, (float)((int)ptr),0.);
-
- }
- return;
- }
-
- /* separate the command into up to three fields */
- if ( !(fields=sscanf(inbuf, "%s%s%s", buf1, buf2, buf3)) ) {
- return;
- }
-
- /* command is the last field */
- switch ( fields ) {
- case 1: command=buf1;
- break;
- case 2: command=buf2;
- break;
- case 3: command=buf3;
- break;
- default: break;
- } /* switch */
-
- /* get instruction corresponding to command */
- if ( instr=ps_cmd2instr(command) ) {
-
- switch ( instr ) {
- /* instructions with two parameters */
- case GE_MOVE:
- case GE_LINE:
- case GE_POLYLINE:
- case GE_POLYGON:
- case GE_CONT:
- case GE_ELLIPSE:
- case GE_ARC:
- sscanf(buf1,"%f",&x); sscanf(buf2,"%f",&y);
- ge_graph(ps_segno, instr, x, y);
- inexec=1;
- break;
-
- /* instructions with one parameter */
- case GE_CIRCLE:
- case GE_ARCEXT:
- case GE_FILL:
- sscanf(buf1, "%f",&x);
- ge_graph(ps_segno, instr, x, 0.);
- inexec=1;
- break;
-
- /* initial attributes or change of attributes */
- case GE_SETCOLOR:
- case GE_SETTYPELINE:
- case GE_SETLINEWIDTH:
- case GE_SETFONT:
- case GE_SETCHARSIZE:
- sscanf(buf1,"%f",&x);
-
- if ( ! inexec )
- /* set initial attribues */
- switch (instr) {
- case GE_SETCOLOR:
- seginfo->attr.color = (int)x;
- break;
- case GE_SETTYPELINE:
- seginfo->attr.linestyle = (int)x;
- break;
- case GE_SETLINEWIDTH:
- seginfo->attr.linewidth = (int)x;
- break;
- case GE_SETFONT:
- seginfo->attr.font = (int) x;
- break;
- case GE_SETCHARSIZE:
- seginfo->attr.charsize = (int) x;
- }
-
- else {
- /* change attribute */
- ge_graph(ps_segno, instr, x, 0.);
- }
- break;
-
- /* trnasformations */
- case GE_TRANSLATE:
- sscanf(buf1,"%f",&(seginfo->attr.tx));
- sscanf(buf2,"%f",&(seginfo->attr.ty));
- break;
- case GE_ROTATE:
- sscanf(buf1,"%f",&(seginfo->attr.ang));
- seginfo->attr.ang /= DEGPERRAD;
- break;
- case GE_SCALE:
- sscanf(buf1,"%f",&(seginfo->attr.sx));
- sscanf(buf2,"%f",&(seginfo->attr.sy));
- break;
-
- /* start new segment */
- case GE_NEW:
- /* create new segment */
- ps_segno=make_new_seg(0);
- seginfo=(struct list *)ge_display_list(ps_segno);
- inexec=0;
- break;
-
- /* close segment */
- case GE_CLOSE:
- seginfo=0;
- /* draw segment */
- ge_draw(ps_segno);
- break;
-
- default:
- /* check that all instructions are properly handled */
- fprintf(stderr, "Internal Error-Action for instruction %d missing.\n",
- instr);
- break;
-
- } /* switch */
-
- } /* if */
-
- } /* ps_read */
-
- @//E*O*F ps.c//
- chmod u=r,g=r,o=r ps.c
-
- echo x - pic.c
- sed 's/^@//' > "pic.c" <<'@//E*O*F pic.c//'
-
- static char SccsId[] = "@(#)pic.c 1.1 6/8/87 Copyright 1987 SBCS-chan";
-
- /*****************************************************************************
-
- (c) Copyright 1987
-
- Lap-Tak Chan
- Computer Science Department
- State University of New York at Stony Brook
- Stony Brook, NY 11794
-
- This software and its documentation may be used, copied, and
- distributed, provided that this legend appear in all copies and
- that it is not copied or distributed for a profit.
-
- No representations is made about the suitability of this software
- for any purpose. It is provided "as is" with no support and no
- express or implied warranty.
-
- *****************************************************************************/
-
- /*****************************************************************************
-
- Pic Output
- ==========
-
- This file contains routines which write the diagram in format suitable
- as input to pic(1), which is a picture drawing preprocessor to troff.
-
- *****************************************************************************/
-
- #include "display.h"
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
-
- #define DEGPERRAD 180./PI
- static FILE *writefile; /* file to write diagram to */
- struct list *ge_display_list();
- static struct attr pic_attr; /* current attributes used for current segment */
- static float sina, cosa;
- static float pic_rms; /* root mean square of x and y scale of current segment */
-
- /* mapping of graphedit fonts to troff fonts */
- static char *pic_font[]=
- { "R", "R", "S", "I", "B" };
-
- /*****************************************************************************
-
- pic_init will do the necessary initialization for the writing.
-
- *****************************************************************************/
-
- pic_init()
- {
- float sx, sy;
- FILE *header;
- char buf[512];
- extern struct saveattr save_attr;
-
- /* indicate beginning of pic input */
- fprintf(writefile, ".PS %.2f\n", save_attr.width/10.);
-
- /* to make pic using full graphedit coordinates */
- fprintf(writefile, "move to (%.4f,%.4f)\n", GE_WIN_X, GE_WIN_Y);
-
- } /* pic_init */
-
- /*****************************************************************************
-
- pic_done do anything necessary to clean up after the writing.
-
- *****************************************************************************/
-
- pic_done()
- {
- FILE *tail;
- char buf[512];
-
- /* indicate end of pic input */
- fprintf(writefile, ".PE\n");
-
- } /* pic_done */
-
- /*****************************************************************************
-
- pic_xform transforms a coordinate of the current segment to the world
- coordiante.
-
- Input
- ix, iy - coordinate in space of current segment
-
- Output
- ox, oy - corresponding world coordinate of (ix,iy) according to
- transformatio of current segment.
-
- *****************************************************************************/
-
- pic_xform(ix, iy, ox, oy)
- float ix, iy, *ox, *oy;
- {
- *ox = cosa * ix * pic_attr.sx - sina * iy * pic_attr.sy + pic_attr.tx;
- *oy = sina * ix * pic_attr.sx + cosa * iy * pic_attr.sy + pic_attr.ty;
-
- } /* pic_xform */
-
- /*****************************************************************************
-
- pic_charsize set a new character size in pic. The actual character
- size is determined from the character size of the current segment, the
- width of the picture, and the scale of the current segment.
-
- *****************************************************************************/
-
- pic_charsize()
- {
- float charsize;
-
- charsize = pic_attr.charsize * pic_rms * save_attr.width / 42.;
- return((int)charsize);
-
- } /* pic_charsize */
-
- /*****************************************************************************
-
- pic_linestyle set a new line style according to the line style of the
- current segment.
-
- *****************************************************************************/
-
- pic_linestyle()
- {
- /* mapping of graphedit line style to pic line style */
- static char *pic_style[] =
- { 0, "dotted 3", "dashed 6", "dashed 2" };
-
- if ( pic_style[pic_attr.linestyle] )
- fprintf(writefile, " %s", pic_style[pic_attr.linestyle]);
-
- } /* pic_linestyle */
-
- /*****************************************************************************
-
- pic_linewidth determine the line width in pic according to the line
- width of the current segment.
-
- Output
- Return the line width determined.
-
- *****************************************************************************/
-
- pic_linewidth()
- {
- /* this formula may need adjustment */
- return ((pic_attr.linewidth)*12+2);
-
- } /* pic_linewidth */
-
- /* set the line width in pic */
- #define pic_set_linewidth() fprintf(writefile,".ps %d\n",\
- pic_linewidth())
-
- /*****************************************************************************
-
- pic_sim_ellipse will simulate the drawing of an ellipse by dividing
- the ellipse into a number of segments and draw each segment with an
- arc. This is necessary because pic cannot draw rotated ellipse.
-
- Coordinates of points on the ellipse are determined by transformation
- of points on a circle at (0,0) with radius 1.
-
- Input
- currx, curry - current world cordinate
- a,b - half of width and height of ellipse
-
- *****************************************************************************/
-
- pic_sim_ellipse(currx, curry, a, b)
- float currx, curry, a, b;
- {
-
- #define PLT_CIRINT 20 /* number of segments to divide into */
- #define PLT_CIRSIZE PLT_CIRINT*2+1 /* size of array necessary */
-
- static int pic_mdl_make = 0;
- static float pic_cir_x[PLT_CIRSIZE];
- static float pic_cir_y[PLT_CIRSIZE];
- extern float ge_radius(); /* from misc.c */
- float radius; /* radius of arc */
- float x1, y1, x2, y2, x3, y3; /* start, mid and end points of arc */
- int i;
-
- /* put the coordinates of points on a circle with center at (0,0)
- and radius 1 in pic_cir_x and pic_cir_y at the first time */
- if ( ! pic_mdl_make ) {
- int count;
- float intv;
-
- intv = PI / PLT_CIRINT;
- for (count=0; count < PLT_CIRSIZE; count ++ ) {
- pic_cir_x[count]=cos(intv*count);
- pic_cir_y[count]=sin(intv*count);
- } /* for */
- pic_mdl_make = 1;
- } /* if */
-
- /* determine the world coordinate of the first point and move there */
- pic_xform(pic_cir_x[0]*a, pic_cir_y[0]*b, &x3, &y3);
- fprintf(writefile, "move to (%.4f,%.4f)\n",
- x3+currx-pic_attr.tx, y3+curry-pic_attr.ty);
-
- /* draw the arcs */
- for ( i=0; i<PLT_CIRSIZE-1; i+=2 ) {
-
- /* make the end point of the last arc the start point */
- x1=x3; y1=y3;
-
- /* determine the world coordinate of the mid point and the end point */
- pic_xform(pic_cir_x[i+1]*a,pic_cir_y[i+1]*b, &x2, &y2);
- pic_xform(pic_cir_x[i+2]*a,pic_cir_y[i+2]*b, &x3, &y3);
-
- /* determine the radius of the arc passing the start, mid and end points */
- radius = ge_radius(x1,y1,x2,y2,x3,y3);
-
- /* draw the arc */
- fprintf(writefile, "arc to (%.4f,%.4f) radius %.4f\n",
- x3+currx-pic_attr.tx, y3+curry-pic_attr.ty, radius);
-
- } /* draw ellipse */
-
- } /* pic_sim_ellipse */
-
- /*****************************************************************************
-
- pic_sim_arc will simulate an arc which is not a real arc after
- transformation of the current segment with a number of small arcs.
-
- Input
- currx, curry - center of arc in world coordinate
- ang1 - start angle in radian, 0 <= ang1 <= 2*PI
- ang2 - end angle in radian, 0 <= ang2 < = 2*PI
- arcradius - radius of arc
-
- *****************************************************************************/
-
- pic_sim_arc(currx, curry, ang1, ang2, arcradius)
- float currx, curry, ang1, ang2, arcradius;
- {
- /* draw arc from smalll arcs */
- float intv, radius;
- extern float ge_radius();
- int count;
- float x1,y1,x2,y2,x3,y3,ang;
-
- /* ensure ang1 < ang2 */
- if ( ang1 > ang2 )
- ang1 -= 2*PI;
-
- /* determine number of segmnets to divide into with a minimum of 3 */
- intv = PI / PLT_CIRINT;
- count = (int)((ang2-ang1)/(2*intv));
- if ( count < 3 ) count = 3;
-
- intv = (ang2-ang1)/(count*2);
-
- /* determine the world coordinate of the first point and move there */
- pic_xform(cos(ang1)*radius,sin(ang1)*arcradius,&x3,&y3);
- fprintf(writefile, "move to (%.4f,%.4f)\n",
- x3+currx-pic_attr.tx,y3+curry-pic_attr.ty);
-
- /* draw the arcs */
- for ( ang = ang1; ang< (ang2-2*intv); ang += 2*intv) {
-
- /* make the end point of the last arc the start point */
- x1=x3; y1=y3;
-
- /* determine the world coordinate of the mid point and the end point */
- pic_xform(cos(ang+intv)*arcradius,
- sin(ang+intv)*arcradius, &x2, &y2);
- pic_xform(cos(ang+2*intv)*arcradius,
- sin(ang+2*intv)*arcradius, &x3, &y3);
-
- /* determine the radius of the arc passing the start, mid and end point */
- radius=ge_radius(x1,y1,x2,y2,x3,y3);
-
- /* draw the arc */
- fprintf(writefile, "arc to (%.4f,%.4f) radius %.4f\n",
- x3+currx-pic_attr.tx, y3+curry-pic_attr.ty, radius);
-
- } /* for */
-
- } /* draw arcs */
-
- /*****************************************************************************
-
- plt_exec will execute an instruction.
-
- Input
- ptr - pointer to instruction
-
- *****************************************************************************/
-
- pic_exec(ptr)
- struct list_item *ptr;
- {
- static float xbuff[512], ybuff[512];
- static int lastinstr=0;
- static int n=0; /* number of points in polygon/polyline */
- static float currx, curry; /* current point */
- int i;
-
- /* execute last polyline/polygon instruction if instruction indicates
- end of the last instruction */
- if ( lastinstr && ptr->instr != GE_CONT ) {
- switch ( lastinstr ) {
- case GE_POLYLINE :
- /* draw polyline */
- for (i=0; i<n; i++) {
- fprintf(writefile, "line to (%.4f,%.4f)", xbuff[i], ybuff[i]);
- pic_linestyle(); /* specify line style */
- fprintf(writefile, "\n");
- } /* for */
-
- /* move to new current point */
- currx = xbuff[n-1];
- curry = ybuff[n-1];
- break;
-
- case GE_POLYGON:
- /* draw polygon */
- fprintf(writefile, "move to (%.4f,%.4f)\n", xbuff[0], ybuff[0]);
- for (i=1; i<n; i++) {
- fprintf(writefile, "line to (%.4f,%.4f)", xbuff[i], ybuff[i]);
- pic_linestyle(); /* specify line style */
- fprintf(writefile, "\n");
- } /* for */
- /* draw last line */
- fprintf(writefile, "line to (%.4f,%.4f)", xbuff[0], ybuff[0]);
- pic_linestyle();
- fprintf(writefile, "\n");
-
- /* update current position */
- currx = xbuff[0];
- curry = ybuff[0];
- break;
- default: ;
- }
- lastinstr = n = 0;
- }
-
- /* execute new instruction */
- switch (ptr->instr) {
-
- /* instructions with single coordinate */
- case GE_MOVE:
- /* move */
- pic_xform(ptr->x, ptr->y, &currx, &curry);
- fprintf(writefile, "move to (%.4f,%.4f)\n", currx, curry);
- break;
-
- case GE_LINE:
- /* line */
- pic_xform(ptr->x, ptr->y, &currx, &curry);
- fprintf(writefile, "line to (%.4f,%.4f)", currx, curry);
- pic_linestyle(); /* specify line style */
- fprintf(writefile, "\n");
- break;
-
- case GE_CIRCLE:
- {
- float radius;
-
- if ( pic_attr.sx == pic_attr.sy ) {
- /* draw a circle if it is a circle after transformation */
- fprintf(writefile, "circle radius %.4f at (%.4f,%.4f)\n",
- ptr->x*pic_attr.sx, currx, curry);
- }
- else {
- if ( pic_attr.ang == 0. ) {
- /* draw ellipse if rotation is 0 */
- fprintf(writefile, "ellipse at (%.4f, %.4f) ht %.4f wid %.4f\n",
- currx, curry, ptr->x*pic_attr.sy*2, ptr->x*pic_attr.sx*2);
- }
- else {
- /* simulate the ellipse */
- pic_sim_ellipse(currx,curry,ptr->x,ptr->x);
- }
- }
- }
- break;
-
- case GE_ELLIPSE:
- {
- float radius;
-
- if ( pic_attr.ang == 0. ) {
- /* draw ellipse if there is no rotation */
- fprintf(writefile, "ellipse at (%.4f, %.4f) ht %.4f wid %.4f\n",
- currx, curry, ptr->y*pic_attr.sy*2, ptr->x*pic_attr.sx*2);
- }
- else {
- /* simulate the ellipse */
- pic_sim_ellipse(currx,curry,ptr->x,ptr->y);
- }
- }
- break;
-
- case GE_ARC:
- case GE_ARCEXT:
- {
- static float ang1, ang2;
-
- if ( ptr->instr == GE_ARC ) {
- ang1 = ptr->x;
- ang2 = ptr->y;
- }
- else {
- if ( pic_attr.sx == pic_attr.sy ) {
- /* draw arc */
- float x1,y1,x2,y2;
-
- pic_xform(cos(ang1)*ptr->x,sin(ang1)*ptr->x,&x1,&y1);
- pic_xform(cos(ang2)*ptr->x,sin(ang2)*ptr->x,&x2,&y2);
- fprintf(writefile, "arc from (%.4f,%.4f) to (%.4f,%.4f) radius %.4f\n",
- x1+currx-pic_attr.tx,y1+curry-pic_attr.ty,
- x2+currx-pic_attr.tx,y2+curry-pic_attr.ty,
- ptr->x*pic_attr.sx);
- }
- else {
- /* simulate the arc */
- pic_sim_arc(currx,curry,ang1,ang2,ptr->x);
- }
- }
- } /* GE_ARC, GE_ARCEXT */
- break;
-
- /* instruction with two or more coordinates */
- case GE_POLYLINE:
- case GE_POLYGON:
- lastinstr=ptr->instr; /* store instruction */
-
- case GE_CONT:
- /* save coordinate of polyline/polygon */
- pic_xform(ptr->x, ptr->y, &xbuff[n], &ybuff[n]);
- n++;
- break;
-
- case GE_TEXT:
- /* draw text */
- fprintf(writefile, ".ft %s\n.ps %d\n\"%s\" ljust at (%.4f,%.4f)\n.ps %d\n",
- pic_font[pic_attr.font],
- pic_charsize(),
- (char *)((int)ptr->x),
- currx, curry,
- pic_linewidth());
- break;
-
- case GE_SETTYPELINE:
- /* update line style */
- pic_attr.linestyle = (int)ptr->x;
- break;
-
- case GE_SETLINEWIDTH:
- /* update line width */
- pic_attr.linewidth = (int)ptr->x;
- pic_set_linewidth();
- break;
-
- case GE_SETFONT:
- /* update font */
- pic_attr.font = (int)ptr->x;
- break;
-
- case GE_SETCHARSIZE:
- /* update character size */
- pic_attr.charsize = (int)ptr->x;
- break;
-
- /* ignore these instructions */
- case GE_SETCOLOR:
- case GE_FILL:
- case GE_CLOSE:
- break;
-
- /* check whether all insturctions are properly handled */
- default :
- fprintf(stderr,
- "Internal Error-Action for instruction %d missing.\n",
- ptr->instr);
- break;
-
- } /* switch */
-
- } /* pic_exec */
-
- /*****************************************************************************
-
- pic_draw_seg will draw a segment according to its display list. It
- just setup the attributes, and scan and execute the instructions on the
- instruction list.
-
- Input
- list - display list of segment
-
- *****************************************************************************/
-
- pic_draw_seg(list)
- struct list *list;
- {
- struct list_item *ptr;
- /* instruction to indicate end of segment */
- static struct list_item closeinstr={GE_CLOSE, 0., 0., NULL};
-
- /* ignore segment if the instruction list is empty */
- if ( !(ptr=list->d_list) )
- return;
-
- /* setup the initial attributes */
- pic_attr=list->attr;
- pic_rms = sqrt((double)((pic_attr.sx*pic_attr.sx+
- pic_attr.sy*pic_attr.sy)/2));
- sina = (double)sin((double)pic_attr.ang);
- cosa = (double)cos((double)pic_attr.ang);
-
- /* initialize the line width */
- pic_set_linewidth();
-
- /* point at beginning of instruction list */
- ptr=ptr->next;
-
- /* scan instruction list */
- do {
- /* execution instruction */
- pic_exec(ptr);
- ptr=ptr->next;
-
- } while ( ptr != list->d_list->next );
-
- /* end of segment */
- pic_exec(&closeinstr);
-
- } /* pic_draw_seg */
-
- /*****************************************************************************
-
- pic_write will write the diagram in pic. It scans the segment list and
- write every user segment not deleted.
-
- Input
- outfile - opened output stream
-
- *****************************************************************************/
-
- pic_write(outfile)
- FILE *outfile;
- {
- extern int ge_seglist;
- extern struct list ge_open[];
- int i;
-
- writefile=outfile;
-
- /* initialize pic */
- pic_init();
-
- /* scan the segment list */
- for ( i=ge_seglist; i; i=ge_open[i].next ) {
-
- /* write undeleted user segment */
- if ( ge_open[i].segno >= GE_MIN_SEG && (! ge_open[i].attr.deleted) ) {
- pic_draw_seg(&(ge_open[i]));
- } /* if */
- } /* for */
-
- /* terminate pic */
- pic_done();
-
- } /* pic_write */
- @//E*O*F pic.c//
- chmod u=r,g=r,o=r pic.c
-
- echo x - plot.c
- sed 's/^@//' > "plot.c" <<'@//E*O*F plot.c//'
-
- static char SccsId[] = "@(#)plot.c 1.1 6/8/87 Copyright 1987 SBCS-achan";
-
- /*****************************************************************************
-
- (c) Copyright 1987
-
- Lap-Tak Chan
- Computer Science Department
- State University of New York at Stony Brook
- Stony Brook, NY 11794
-
- This software and its documentation may be used, copied, and
- distributed, provided that this legend appear in all copies and
- that it is not copied or distributed for a profit.
-
- No representations is made about the suitability of this software
- for any purpose. It is provided "as is" with no support and no
- express or implied warranty.
-
- *****************************************************************************/
-
- /*****************************************************************************
-
- Plot Output
- ===========
-
- This file contains routines which write the diagram in plot(5) format.
- The output file is actually written by routines in the plot(3) library.
-
- Filters for many graphic display terminal, laser printers, plotters
- and even regular terminals are available for files in plot(5) format.
-
- *****************************************************************************/
-
- #include "display.h"
- #include <stdio.h>
- #include <math.h>
-
- /* scale used to maintain significance of coordinates when floating
- point coordinates are convert to integer coordinates */
- #define SCALE 10
-
- static double sina, cosa; /* sin and cos of rotation of current segment */
-
- /* mapping of graphedit line styles to plot line styles */
- static char *plt_linestyle[] =
- { "solid", "dotted", "shortdashed", "dotdashed" };
-
- static struct attr curr_attr; /* attributes of current segment */
-
- /* from display.c */
- extern int ge_seglist; /* segment list */
- extern struct list ge_open[]; /* display list of segments */
-
- /*****************************************************************************
-
- plt_write will write the diagram with routines in plot(3). It
- scans the segment list and write every user segment not deleted.
-
- *****************************************************************************/
-
- plt_write()
- {
- int i;
-
- /* initialize plot and define the coordiante space */
- openpl();
- space(0,0,(int)GE_WIN_X*SCALE, (int)GE_WIN_Y*SCALE);
-
- /* scan the segment list */
- for ( i=ge_seglist; i; i=ge_open[i].next ) {
-
- /* write undeleted user segment */
- if ( ge_open[i].segno >= GE_MIN_SEG && (! ge_open[i].attr.deleted) ) {
- plt_draw_seg(&(ge_open[i]));
- } /* if */
-
- } /* for */
-
- /* close plot */
- closepl();
-
- } /* plt_write */
-
- /*****************************************************************************
-
- plt_draw_seg will draw a segment according to its display list. It
- just setup the attributes, and scan and execute the instructions on the
- instruction list.
-
- Input
- list - display list of segment
-
- *****************************************************************************/
-
- plt_draw_seg(list)
- struct list *list;
- {
- struct list_item *ptr;
- /* instruction to indicate end of segment */
- static struct list_item closeinstr={GE_CLOSE, 0., 0., NULL};
-
- /* ignore segment if the instruction list is empty */
- if ( !(ptr=list->d_list) )
- return;
-
- /* setup the initial attributes */
- curr_attr = list->attr;
-
- /* initialize the line style */
- linemod(plt_linestyle[curr_attr.linestyle]);
-
- sina = (double)sin((double)curr_attr.ang);
- cosa = (double)cos((double)curr_attr.ang);
-
- /* point to beginning of instruction list */
- ptr=ptr->next;
-
- /* scan instruction list */
- do {
- /* execution instruction */
- plt_exec(ptr);
- ptr=ptr->next;
-
- } while ( ptr !=list->d_list->next );
-
- /* end of segment */
- plt_exec(&closeinstr);
-
- } /* plt_draw_seg */
-
- /*****************************************************************************
-
- plt_xform will transform a coordinate of the current segment to world
- coordinate and adjust its significance.
-
- Input
- fx, fy - coordinate in coordinate system of current segment
-
- Output
- ix, iy - world coordinate
-
- *****************************************************************************/
-
- plt_xform(fx,fy,ix,iy)
- float fx, fy;
- int *ix, *iy;
- {
- float x, y;
-
- /* transform coordinate */
- x = cosa * fx * curr_attr.sx - sina * fy * curr_attr.sy + curr_attr.tx;
- y = sina * fx * curr_attr.sx + cosa * fy * curr_attr.sy + curr_attr.ty;
-
- /* adjust significance */
- *ix = (int)(x * SCALE + 0.5);
- *iy = (int)(y * SCALE + 0.5);
-
- } /* plt_xform */
-
- /*****************************************************************************
-
- plt_sim_ellipse will simulate the drawing of an ellipse by dividing
- the ellipse into a number of segments and draw each segment with an
- arc. This is necessary because plot(3) cannot draw ellipse.
-
- Coordinates of points on the ellipse are determined by transformation
- of points on a circle at (0,0) with radius 1.
-
- Input
- xcur, ycur - current world coordinate
- a,b - half of width and height of ellipse
-
- *****************************************************************************/
-
- plt_sim_ellipse(xcur, ycur, a, b)
- int xcur, ycur;
- float a, b;
- {
-
- #define PLT_CIRINT 20 /* number of segments to divide into */
- #define PLT_CIRSIZE PLT_CIRINT*2+1 /* size of array necessary */
-
- static int plt_mdl_make = 0;
- static float plt_cir_x[PLT_CIRSIZE];
- static float plt_cir_y[PLT_CIRSIZE];
- extern float ge_radius2(); /* from misc.c */
- float radius; /* radius of arc */
- int x1, y1, x2, y2, x3, y3;
- float x,y;
- int i;
-
- /* put the coordinates of points on a circle with center at (0,0)
- and radius 1 in plt_cir_x and plt_cir_y at the first time */
- if ( ! plt_mdl_make ) {
- int count;
- float intv;
-
- intv = PI / PLT_CIRINT;
- for (count=0; count < PLT_CIRSIZE; count ++ ) {
- plt_cir_x[count]=cos(intv*count);
- plt_cir_y[count]=sin(intv*count);
- }
- plt_mdl_make = 1;
-
- } /* if */
-
- /* determine the world coordinate of the first point */
- plt_xform(plt_cir_x[0]*a, plt_cir_y[0]*b, &x3, &y3);
-
- /* draw the arcs */
- for ( i=0; i<PLT_CIRSIZE-1; i+=2 ) {
-
- /* make the end point of the last arc the start point */
- x1=x3; y1=y3;
-
- /* determine the world coordinate of the mid point and the end point */
- plt_xform(plt_cir_x[i+1]*a,plt_cir_y[i+1]*b, &x2, &y2);
- plt_xform(plt_cir_x[i+2]*a,plt_cir_y[i+2]*b, &x3, &y3);
-
- /* determine the center of the arc passing the start point, midpoint and
- end point */
- (void) ge_radius2((float)x1,(float)y1,(float)x2,(float)y2,
- (float)x3,(float)y3,&x,&y);
-
- /* draw the arc */
- arc((int)(x+xcur-curr_attr.tx*SCALE),(int)(y+ycur-curr_attr.ty*SCALE),
- (int)(x1+xcur-curr_attr.tx*SCALE),(int)(y1+ycur-curr_attr.ty*SCALE),
- (int)(x3+xcur-curr_attr.tx*SCALE),(int)(y3+ycur-curr_attr.ty*SCALE));
-
- } /* for */
-
- } /* plt_sim_ellipse */
-
- /*****************************************************************************
-
- plt_sim_arc will simulate an arc which is not a real arc after
- transformation of the current segment with a number of small arcs.
-
- Input
- cx, cy - center of arc in world coordinate
- ang1 - start angle in radian, 0 <= ang1 <= 2*PI
- ang2 - end angle in radian, 0 <= ang2 <= 2*PI
- arcradius - radius of arc
-
- *****************************************************************************/
-
- plt_sim_arc(cx,cy,ang1,ang2,arcradius)
- int cx,cy;
- float ang1,ang2,arcradius;
- {
- float intv, radius;
- extern float ge_radius2();
- int count;
- int x1,y1,x2,y2,x3,y3; /* start, mid and end point of small arc */
- float ang,x,y;
-
- intv = PI / PLT_CIRINT;
-
- /* ensure ang1 is less than ang2 */
- if ( ang1 > ang2 )
- ang1 -= 2*PI;
-
- /* determine how many small arcs it will be divided into,
- the minimum is 3 */
- count = (int)((ang2-ang1)/(2*intv));
- if ( count < 3 ) count = 3;
-
- intv = (ang2-ang1)/(count*2);
-
- /* transform the first point */
- plt_xform(cos(ang1)*arcradius,sin(ang1)*arcradius,&x3,&y3);
-
- /* draw the arcs */
- for ( ang = ang1; ang< (ang2-2*intv); ang += 2*intv) {
-
- /* make end point of last arc the start point */
- x1=x3; y1=y3;
-
- /* transform mid point */
- plt_xform(cos(ang+intv)*arcradius,
- sin(ang+intv)*arcradius, &x2, &y2);
-
- /* transform end point */
- plt_xform(cos(ang+2*intv)*arcradius,
- sin(ang+2*intv)*arcradius, &x3, &y3);
-
- /* determine radius of arc */
- (void)ge_radius2((float)x1,(float)y1,(float)x2,(float)y2,
- (float)x3,(float)y3,&x,&y);
-
- /* draw small arc */
- arc((int)(x+cx-curr_attr.tx*SCALE+0.5),
- (int)(y+cy-curr_attr.ty*SCALE+0.5),
- (int)(x1+cx-curr_attr.tx*SCALE),
- (int)(y1+cy-curr_attr.ty*SCALE),
- (int)(x3+cx-curr_attr.tx*SCALE),
- (int)(y3+cy-curr_attr.ty*SCALE));
-
- } /* for */
-
- } /* plt_sim_arc */
-
- /*****************************************************************************
-
- plt_exec will execute an instruction. It call routines in plot(3) to
- actually do the drawing.
-
- Input
- ptr - pointer to instruction
-
- *****************************************************************************/
-
- plt_exec(ptr)
- struct list_item *ptr;
- {
- static int xbuff[512], ybuff[512];
- static int lastinstr=0;
- static int n=0; /* number of points in polygon/polyline */
- static int xcur, ycur; /* current point */
- int i;
-
- /* check whether the list of points for polygon/polyline end */
- if ( lastinstr && ptr->instr !=GE_CONT ) {
- switch ( lastinstr ) {
- case GE_POLYLINE:
- /* draw polyline */
- move (xcur, ycur);
- for (i=0; i<n; i++) {
- cont(xbuff[i], ybuff[i]);
- }
- xcur=xbuff[n-1];
- ycur=ybuff[n-1];
- break;
-
- case GE_POLYGON:
- /* draw polygon */
- move(xbuff[0],ybuff[0]);
- for ( i=1; i<n; i++ ) {
- cont(xbuff[i], ybuff[i]);
- }
- cont(xbuff[0],ybuff[0]);
- xcur=xbuff[0];
- ycur=ybuff[0];
- break;
-
- } /* switch */
- lastinstr = n = 0;
- } /* if */
-
- switch (ptr->instr) {
-
- case GE_MOVE:
- plt_xform(ptr->x, ptr->y, &xcur, &ycur);
- move(xcur, ycur);
- break;
-
- case GE_LINE:
- {
- int tmpx, tmpy;
- plt_xform(ptr->x, ptr->y, &tmpx, &tmpy);
- line(xcur, ycur, tmpx, tmpy);
- xcur=tmpx;
- ycur=tmpy;
- }
- break;
-
- case GE_CIRCLE:
- if ( curr_attr.sx == curr_attr.sy ) {
- /* draw it as a circle if it is still a circle after
- transformation of current segment */
- int radius;
-
- radius = (int)(ptr->x*SCALE+0.5);
- circle(xcur,ycur,radius);
- }
- else {
- plt_sim_ellipse(xcur,ycur,ptr->x,ptr->x);
- }
- break;
-
- case GE_ELLIPSE:
- /* draw ellipse */
- plt_sim_ellipse(xcur,ycur,ptr->x,ptr->y);
- break;
-
- case GE_ARC:
- case GE_ARCEXT:
- {
- static float ang1, ang2;
-
- if ( ptr->instr == GE_ARC ) {
- /* save angles of arc */
- ang1 = ptr->x;
- ang2 = ptr->y;
- } /* GE_ARC */
-
- else {
-
- if ( curr_attr.sx == curr_attr.sy ) {
- /* draw arc as one arc if it is a real arc after
- transformation of current segment */
- int x1,y1,x2,y2;
-
- /* transform start point and end point of arc */
- plt_xform(cos(ang1)*ptr->x,sin(ang1)*ptr->x,&x1,&y1);
- plt_xform(cos(ang2)*ptr->x,sin(ang2)*ptr->x,&x2,&y2);
-
- /* draw arc */
- arc(xcur,ycur,
- (int)(x1+xcur-curr_attr.tx*SCALE),
- (int)(y1+ycur-curr_attr.ty*SCALE),
- (int)(x2+xcur-curr_attr.tx*SCALE),
- (int)(y2+ycur-curr_attr.ty*SCALE));
- }
- else {
- /* draw 'arc' with a number of small arcs */
- plt_sim_arc(xcur,ycur,ang1,ang2,ptr->x);
- }
-
- } /* GE_ARCEXT */
-
- } /* case GE_ARC, GE_ARCEXT */
- break;
-
- case GE_POLYLINE:
- case GE_POLYGON:
- lastinstr=ptr->instr;
-
- case GE_CONT:
- plt_xform(ptr->x, ptr->y, &xbuff[n], &ybuff[n]);
- n++;
- break;
-
- case GE_SETTYPELINE:
- /* change the line style */
- linemod(plt_linestyle[(int)ptr->x]);
- break;
-
- case GE_TEXT:
- /* draw text */
- label((char *)((int)ptr->x));
- break;
-
- /* ignore these instructions */
- case GE_SETCOLOR:
- case GE_SETFONT:
- case GE_SETCHARSIZE:
- case GE_SETLINEWIDTH:
- case GE_FILL:
- case GE_CLOSE:
- break;
-
- /* check that all instructions are handled properly */
- default:
- fprintf(stderr,
- "Internal Error-Action for instruction %d missing.\n",
- ptr->instr);
- break;
-
- } /* switch */
-
- } /* plt_exec */
- @//E*O*F plot.c//
- chmod u=r,g=r,o=r plot.c
-
- echo Inspecting for damage in transit...
- temp=/tmp/shar$$; dtemp=/tmp/.shar$$
- trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
- cat > $temp <<\!!!
- 314 1039 8695 display.c
- 689 1901 18053 ps.c
- 579 1887 16700 pic.c
- 464 1461 12850 plot.c
- 2046 6288 56298 total
- !!!
- wc display.c ps.c pic.c plot.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
- if [ -s $dtemp ]
- then echo "Ouch [diff of wc output]:" ; cat $dtemp
- else echo "No problems found."
- fi
- exit 0
-
-